import 'dart:convert';
import 'package:flutter_map_demo/t3_map_plugin/map/core/t3_location.dart';
import 'package:flutter_map_demo/t3_map_plugin/route/core/t3_route_model.dart';
import 'package:flutter_map_demo/t3_map_plugin/route/route_manager/t3_route_data_service.dart';
import 'package:t3_data_service/biz_data_source/map/point/service/map_point_service.dart';
import 'package:t3_data_service/data_provider/map_sctx/t3_map_sctx_provider.dart';
import 'package:t3_data_service/data_provider/orion/orion_hash.dart';
import 'package:t3_data_service/data_provider/orion/orion_service.dart';
import 'package:t3_data_service/get_data_service.dart';
import 'package:t3_foundation/t3_foundation.dart';

import '../../t3_map_platform_interface.dart';

class T3RouteManager {
  /// 获取步行路线
  static Future<T3RouteModel?> getWalkRoute({
      required T3MapType mapType,
      required T3LocationCoordinate2D origin,
      required T3LocationCoordinate2D destination}) async {
    
    ///是否使用T3的API进行算路
    int mapApiBucket = OrionService.instance.switchInfo.mapApiBucket ?? 0;
    bool useApi = false;
    if (mapApiBucket > 0) {
      useApi = await OrionHashTool.bucketWithDeviceUUID(mapApiBucket);
    }
    if (useApi) {
      return T3RouteDataService.getWalkRouteFromService(origin: origin, destination: destination);
    } 
    else {
      final routeValue = await T3MapPlatform.instance.getWalkRoute(mapType: mapType, origin: origin, destination: destination);
      if (routeValue != null) {
        try {
          final json = jsonDecode(routeValue);
          final result = T3RouteResultModel.fromSDKRouteJson(json, mapType);
          return result?.routes.safeAccess(0);
        } catch (e) {
          return null;
        }
      }
      else {
        return null;
      }
    }
  }

  /// 获取驾车路线
  /// 优先使用gis：notoken/ws/lbs/v2/route/eval/direction/driving接口进行请求，接口会默认重试3次
  /// 如果3次后依旧失败，则降级使用SDK进行算路
  static Future<T3RouteResultModel?> getDrivingRoute({
    required T3MapType mapType,
    required T3LocationCoordinate2D origin,
    required T3LocationCoordinate2D destination,
    List<T3LocationCoordinate2D>? viaPoints,
    String? originPoiId,
    String? destPoiId,
    /// 用于gis计算路线标签使用，用于获取对应城市的计价规则，建议传入，如果没有传入，需要日志提醒
    String? areaCode,
    double? departureTime,
  }) async {

    if (areaCode == null) {
      //TODO: 日志
    }

    /// 优先使用gis：notoken/ws/lbs/v2/route/eval/direction/driving接口进行请求，接口会默认重试3次
    var routeValue = await T3RouteDataService.getGisRouteFromService(
      mapType: mapType, origin: origin, destination: destination, viaPoints: viaPoints, originPoiId: originPoiId, destPoiId: destPoiId, areaCode: areaCode, departureTime: departureTime
    );
    //如果路线获取失败，则降级使用SDK进行算路
    if (routeValue == null) {
      //TODO: 日志
      final value = await T3MapPlatform.instance.getDriveRoute(mapType: mapType, 
                                                              origin: origin, 
                                                              destination: destination,
                                                              viaPoints: viaPoints,
                                                              originPoiId: originPoiId,
                                                              destPoiId: destPoiId,
                                                              departureTime: departureTime
                                                              );

      if (value != null) {
        try {
          final json = jsonDecode(value);
          routeValue = T3RouteResultModel.fromSDKRouteJson(json, mapType);
        } catch (e) {
          //TODO: 日志
        }
      }
      else {
        //TODO: 日志
      }
    }
    return routeValue;
  }

  /// 获取驾车路线，该方法属于定制方法，使用场景局限性较大
  /// 优先使用gis：notoken/ws/lbs/v2/route/eval/direction/driving接口进行请求，接口会默认重试3次
  /// 如果3次后依旧失败，则降级使用SDK进行算路
  /// origin：起点显示经纬度
  /// arrriveOrigin：起点到达点经纬度
  /// destination：终点显示点经纬度
  /// arrriveDestination：终点显示点经纬度
  /// viaPoints：途经点
  /// originPoiId：起点poiId
  /// destPoiId：终点poiId
  /// areaCode：用于gis计算路线标签使用，用于获取对应城市的计价规则，建议传入，如果没有传入，需要日志提醒
  /// departureTime：用车时间
  static Future<T3DriveRouteResultUnionModel?> getDrivingRouteUnionEndPointRecommend({
    required T3MapType mapType,
    required T3LocationCoordinate2D origin,
    required T3LocationCoordinate2D? arriveOrigin,
    required T3LocationCoordinate2D destination,
    required T3LocationCoordinate2D? arriveDestination,
    List<T3LocationCoordinate2D>? viaPoints,
    String? originPoiId,
    String? destPoiId,
    required String? areaCode,
    double? departureTime,
  }) async {

    final originValue = arriveOrigin ?? origin;

    //判断是否有终点导航点经纬度，如果没有，则使用下车点服务进行数据补充，超时时间设置为2s
    T3LocationCoordinate2D? retArriveDestination;
    String? destinationPoiId;
    
    if (arriveDestination == null) {
      final dataService = getService<RecommendPointsService>();
      const int mode = 4;
      const String mapLevel = 'mapLevel17';
      final poi = await dataService.getRecommendEndPoints(longitude: destination.longitude.toString(), 
                                        latitude: destination.latitude.toString(), 
                                        adCode: areaCode,
                                        poiId: destPoiId,
                                        startLng: originValue.longitude.toString(),
                                        startLat: originValue.latitude.toString(),
                                        mode: mode,
                                        mapLevel: mapLevel,
                                        timeOut: 2,
                                        );
      if (poi != null) {
        final first = poi.pointList.safeAccess(0);
        if (first != null && first.isPriorAbsorb != null) {
          final arrive = first.getCoordinate();
          if (first.isPriorAbsorb == 1 && arrive != null) {
            retArriveDestination = T3LocationCoordinate2D(longitude: arrive.longitude, latitude: arrive.latitude);
            destinationPoiId = first.poiId;
          }
        }
      }
    }
    else {
      retArriveDestination = arriveDestination;
    }

    //处理算路经纬度，优先级：到达点经纬度 > 显示经纬度
    final destinationValue = retArriveDestination ?? destination;

    final route = await getDrivingRoute(mapType: mapType, origin: originValue, destination: destinationValue,viaPoints: viaPoints, originPoiId: originPoiId, destPoiId: destPoiId, areaCode: areaCode, departureTime: departureTime);

    if (route != null) {
      return T3DriveRouteResultUnionModel(routeResult: route, arriveDestination: retArriveDestination, destinationPoiId: destinationPoiId);
    } else {
      return null;
    }
  }
}

class T3DriveRouteResultUnionModel {
    T3RouteResultModel routeResult;
    T3LocationCoordinate2D? arriveDestination;
    String? destinationPoiId;
    
    T3DriveRouteResultUnionModel({
      required this.routeResult,
      required this.arriveDestination,
      required this.destinationPoiId
    });
  }